package dmitrygusev.ratings.services;

import dmitrygusev.io.StringUtils;
import dmitrygusev.ratings.model.Movie;

public class Matcher {

	public static void normalizeTitles(Movie movie) {
		movie.setTitle(normalizeTitle(movie.getTitle()));
		movie.setTitle2(normalizeTitle(movie.getTitle2()));
	}

	public static boolean matchesByTitle(Movie movie, String query) {
		return matches(movie.getTitle(), query) 
			|| matches(movie.getTitle2(), query);
	}

	public static boolean matches(String title, String query) {
		if (StringUtils.isNullOrEmpty(title)) {
			return false;
		}
		
		query = query.toLowerCase();
		
		if (fuzzyEquals(title.toLowerCase(), query)) {
			return true;
		}
		
		title = normalizeTitle(title);
		
		if (fuzzyEquals(title.toLowerCase(), query)) {
			return true;
		}
		
		return false;
	}

	/**
	 * 
	 * @param text not null
	 * @param query not null
	 * @return
	 */
	public static boolean fuzzyEquals(String text, String query) {
		String[] textParts = text.split(" ");
		String[] queryParts = query.split(" ");
		
		int matchesCount = 0;
		
		for (String queryPart : queryParts) {
			for (String textPart : textParts) {
				
				queryPart = queryPart.trim();
				textPart = textPart.trim();
				
				int distance = LevensteinDistanceService.calculate(
						queryPart, textPart);
				
				double distanceMatch = 1d * distance / textPart.length();
				
				if (distanceMatch <= 0.5) {
					//	Считаем количество совпавших слов из запроса
					matchesCount++;
					break;
				}
			}
		}
		
		double matchWeight = 1d * matchesCount / queryParts.length;
		
		return matchWeight > 0.5;
	}

	public static String normalizeTitle(String title) {
		if (StringUtils.isNullOrEmpty(title)) {
			return title;
		}
		
		if (title.endsWith(", The") || 
				title.endsWith(", Le") || 
				title.endsWith(", El") || 
				title.endsWith(", La")) {
			int commaIndex = title.lastIndexOf(", ");
			if (commaIndex > 0) {
				title = title.substring(commaIndex + ", ".length()) + " " 
					+ title.substring(0, commaIndex);
			}
		}
		return title;
	}

	public static boolean titlesAreTheSame(String a, String b) {
		//	TODO Need better way to determine equality:
		
		//	 1. respect HTML entities aka special chars
		//	 2. ignore punctuation
		
		a = cleanupTitle(a);
		b = cleanupTitle(b);
		
		return a.equalsIgnoreCase(b);
	}

	private static String cleanupTitle(String a) {
		return a.replaceAll(":", "").replaceAll("-", "").replaceAll("  ", " ");
	}

}
